import { ConfigService } from '@nestjs/config'
import compression from 'compression'
import cors from 'cors'
import express from 'express'
import { rateLimit } from 'express-rate-limit'
import helmet from 'helmet'
import { createServer } from 'http'
import mongoose from 'mongoose'
import { Server } from 'socket.io'
import { errorHandler } from './middlewares/errorHandler'
import { authRoutes } from './routes/auth'
import { paymentRoutes } from './routes/payment'
import { roomRoutes } from './routes/room'
import userRoutes from './routes/users'
import { AuthService } from './services/auth/AuthService'
import { ChatService } from './services/chat/ChatService'
import { DanmakuFilter } from './services/danmaku/DanmakuFilter'
import { GiftService } from './services/gift/GiftService'
import { PaymentService } from './services/payment/PaymentService'
import { RedisService } from './services/redis/RedisService'
import { RoomService } from './services/room/RoomService'
import { RoomStateService } from './services/room/RoomStateService'
import { StreamingService } from './services/streaming/StreamingService'
import { initializeSocketServer } from './socket'
import { logger } from './utils/logger'

// 创建Express应用
const app = express()
const httpServer = createServer(app)
const io = new Server(httpServer, {
  cors: {
    origin: process.env.CORS_ORIGIN || '*',
    methods: ['GET', 'POST'],
    credentials: true,
  },
  pingTimeout: 60000,
  pingInterval: 25000,
})

// 中间件配置
app.use(cors())
app.use(helmet())
app.use(compression())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// 环境变量校验
const requiredEnvVars = ['MONGODB_URI', 'REDIS_URL', 'CORS_ORIGIN']
requiredEnvVars.forEach((env) => {
  if (!process.env[env]) {
    logger.error(`缺少必要环境变量: ${env}`)
    process.exit(1)
  }
})

// 请求日志
app.use((req, res, next) => {
  logger.info(`${req.method} ${req.url}`)
  next()
})

// 健康检查
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok' })
})

// 速率限制
app.use(
  rateLimit({
    windowMs: 15 * 60 * 1000, // 15分钟
    max: 500, // 限制500次请求
    message: '请求过于频繁，请稍后再试',
    skip: (req) => req.url === '/health', // 健康检查不限制
  })
)

// 初始化服务
const configService = new ConfigService()
const redisService = new RedisService(configService)
const roomStateService = new RoomStateService(redisService)
const danmakuFilter = new DanmakuFilter(configService)

const chatService = new ChatService(
  io,
  configService,
  redisService,
  roomStateService,
  danmakuFilter
)
const roomService = new RoomService(io, configService)
const streamingService = new StreamingService(configService, redisService, roomStateService, io)
const giftService = new GiftService(io, redisService, roomStateService, configService)
const authService = new AuthService(configService, redisService)
const paymentService = new PaymentService(configService, redisService)

// 路由配置
app.use('/api/auth', authRoutes)
app.use('/api/rooms', roomRoutes)
app.use('/api/users', userRoutes)
app.use('/api/payment', paymentRoutes)

// WebSocket处理
initializeSocketServer(io)

// 错误处理
app.use(errorHandler)

// 数据库连接
const connectWithRetry = () => {
  mongoose
    .connect(process.env.MONGODB_URI, {
      retryWrites: true,
      w: 'majority',
      serverSelectionTimeoutMS: 5000,
      socketTimeoutMS: 5000,
      connectTimeoutMS: 5000,
    })
    .then(() => {
      logger.info('MongoDB连接成功')
    })
    .catch((err) => {
      logger.error('MongoDB连接失败:', err)
      setTimeout(connectWithRetry, 5000)
    })
}

connectWithRetry()

// 启动服务器
const PORT = process.env.PORT || 3000
httpServer.listen(PORT, () => {
  logger.info(`服务器运行在 http://localhost:${PORT}`)

  // 输出环境信息
  logger.info('环境配置:')
  logger.info(`- 运行模式: ${process.env.NODE_ENV}`)
  logger.info(`- 数据库: ${process.env.MONGODB_URI}`)
  logger.info(`- Redis: ${process.env.REDIS_URL}`)
  logger.info(`- 跨域配置: ${process.env.CORS_ORIGIN}`)
})

// 优雅退出
process.on('SIGTERM', () => {
  logger.info('收到 SIGTERM 信号，准备关闭服务器')
  httpServer.close(() => {
    logger.info('HTTP服务器已关闭')
    mongoose.connection.close(false).then(() => {
      logger.info('MongoDB连接已关闭')
      process.exit(0)
    })
  })
})

export {
  app,
  authService,
  chatService,
  giftService,
  httpServer,
  io,
  paymentService,
  roomService,
  streamingService,
}
